package cn.rengy.web.framework.support.xss;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.rengy.tool.web._WebUtils;


public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
	private static final Logger LOGGER = LoggerFactory.getLogger(XssHttpServletRequestWrapper.class);
	HttpServletRequest orgRequest = null;
	private byte[] buffer;
    public XssHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
    	super(request);
    	orgRequest=request;
    	/*Enumeration<String> headerNames=request.getHeaderNames();
    	LOGGER.debug("=HEADER=");
    	while(headerNames.hasMoreElements()) {
    		String name=headerNames.nextElement();
    		String value=request.getHeader(name);
    		LOGGER.debug(name+"="+value);
    	}
    	LOGGER.debug("=HEADER=");*/
		//缓存数据使ServletInputStream可以重复读取
    	//setPayload();
    }
    
    private void setPayload() throws IOException{
    	//String contentType=orgRequest.getHeader(HttpHeaders.CONTENT_TYPE);
		//if(contentType!=null&&MediaType.MULTIPART_FORM_DATA.isCompatibleWith(MediaType.valueOf(contentType))) {
			//文件上传
		//}
    	//非json类型，直接返回
        if(_WebUtils.isAjaxRequest(orgRequest)){
        	buffer=IOUtils.toByteArray(super.getInputStream());
            //ajax请求对payload数据进行xss过滤
            
            String json=IOUtils.toString(buffer,"utf-8");
            //为空，直接返回
            if (StringUtils.isBlank(json)) {
                return;
            }
            //xss过滤
            json = cleanPayload(json);
            this.buffer=json.getBytes("utf-8");
        }
    }
    /*@Override
    public ServletInputStream getInputStream() throws IOException {
    	return new BufferedServletInputStream(this.buffer);
    }
    class BufferedServletInputStream extends ServletInputStream {
        private ByteArrayInputStream inputStream;
        public BufferedServletInputStream(byte[] buffer){
            this.inputStream = new ByteArrayInputStream(buffer);
        }
		@Override
		public boolean isFinished() {
			// TODO Auto-generated method stub
			return false;
		}
		@Override
		public boolean isReady() {
			// TODO Auto-generated method stub
			return false;
		}
		@Override
		public void setReadListener(ReadListener listener) {
			// TODO Auto-generated method stub
			
		}
		@Override
		public int read() throws IOException {
			return inputStream.read();
		}
    }*/
    /* *
     * @Description 重写  数组参数过滤
     * @Param [parameter]
     * @Return java.lang.String[]
     */
    @Override
    public String[] getParameterValues(String parameter) {
        String[] values = super.getParameterValues(parameter);
        if (values == null) {
            return null;
        }
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0 ; i < count ; i++ ) {
            encodedValues[i] = cleanParam(values[i]);
        }
        return encodedValues;
    }

    @Override
    public Map<String,String[]> getParameterMap() {
        Map<String,String[]> primary = super.getParameterMap();
        Map<String,String[]> result = new HashMap<>();
        for (Map.Entry<String,String[]> entry : primary.entrySet()) {
            result.put(entry.getKey(),filterEntryString(entry.getValue()));
        }
        return result;
    }

    @Override
    public String getParameter(String parameter) {
        return cleanParam(super.getParameter(parameter));
    }

    @Override
    public String getHeader(String name) {
        return cleanParam(super.getHeader(name));
    }

    @Override
    public Cookie[] getCookies() {
        Cookie[] cookies = super.getCookies();
        if (cookies != null) {
            for (int i = 0 ; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                cookie.setValue(cleanParam(cookie.getValue()));
            }
        }
        return cookies;
    }

    /* *
     * @Description  过滤字符串数组不安全内容
     * @Param [value]
     * @Return java.lang.String[]
     */
    private String[] filterEntryString(String[] value) {
        for (int i = 0; i < value.length; i++) {
            value[i] = cleanParam(value[i]);
        }
        return value;
    }

    
    /*private String xssEncode(String input) {
        // 过滤XSS 
        return SimpleXssFilterUtils.clean(input);
        //return StringEscapeUtils.escapeHtml4(value);
    }*/
    /**
     * 获取最原始的request
     */
    public HttpServletRequest getOrgRequest() {
        return orgRequest;
    }

    /**
     * 获取最原始的request
     */
    public static HttpServletRequest getOrgRequest(HttpServletRequest request) {
        if (request instanceof XssHttpServletRequestWrapper) {
            return ((XssHttpServletRequestWrapper) request).getOrgRequest();
        }

        return request;
    }
    
    private String cleanParam(String input){
    	return clean(input,0);
    }
    private static String clean(String input,int type) {
        if (input == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder(input.length()+16);
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            //if (type == 0) {//param参数
            //	return StringEscapeUtils.escapeHtml4(input);
            //}else{//payload参数
            	switch (c) {
                case '<':
                	sb.append("&lt;");
                    break;
                case '>':
                	sb.append("&gt;");
                    break;
//                case '%':
//                	processUrlEncoder( sb,  input,  i);
//                	break;
//                case '&':
//                	sb.append("&amp;");
//                    break;
                default:
                	sb.append(c);
                }
            //}
        }
        return sb.toString();
    }
    private String cleanPayload(String input){
    	return input;
    	//return clean(input,1);
    }
    private static void processUrlEncoder(StringBuilder sb, String s, int index) {
        if (s.length() >= index + 2) {
            // %3c, %3C
            if (s.charAt(index + 1) == '3' && (s.charAt(index + 2) == 'c' || s.charAt(index + 2) == 'C')) {
                sb.append("&lt;");//'＜'
                //TODO i=i+2
                return;
            }
            // %3c (0x3c=60)
            if (s.charAt(index + 1) == '6' && s.charAt(index + 2) == '0') {
                sb.append("&lt;");//'＜'
              //TODO i=i+2
                return;
            }
            // %3e, %3E
            if (s.charAt(index + 1) == '3' && (s.charAt(index + 2) == 'e' || s.charAt(index + 2) == 'E')) {
                sb.append("&gt;");//'＞'
                //TODO i=i+2
                return;
            }
            // %3e (0x3e=62)
            if (s.charAt(index + 1) == '6' && s.charAt(index + 2) == '2') {
                sb.append("&gt;");//'＞'
               //TODO i=i+2
                return;
            }
        }
        sb.append(s.charAt(index));
    }
}
